import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import TWEEN from "@tweenjs/tween.js";
import { TransformControls } from "three/addons/controls/TransformControls.js";
export default class InitScene {
    constructor(id) {
        this.id = id;
        this.Scene = null;
        this.Camera = null;
        this.Renderer = null;
        this.Controls = null;
        this.Modal = null;

        this.init();
    }

    //初始化场景
    init() {
        let dom = document.getElementById(this.id);
        let scene = new THREE.Scene();
        let camera = new THREE.PerspectiveCamera(
            50,
            dom.clientWidth / dom.clientHeight,
            0.1,
            1000
        );
        let renderer = new THREE.WebGLRenderer({
            antialias: true,
            logarithmicDepthBuffer: true,
        });

        camera.position.set(500, 500, 500);

        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(dom.clientWidth, dom.clientHeight);
        renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        renderer.shadowMap.enabled = true;
        // let axesCorner = new THREE.AxesHelper(5)
        // scene.add(axesCorner)
        dom.appendChild(renderer.domElement);

        //添加控制器
        let controls = new OrbitControls(camera, renderer.domElement);

        controls.dampingFactor = 0.01;
        controls.minPolarAngle = 0;
        controls.maxPolarAngle = 1.5;

        controls.addEventListener("change", () => {
            renderer.render(scene, camera);
        });

        //添加环境光
        let ambient = new THREE.AmbientLight("#ffffff", 0.3);
        scene.add(ambient);
        let directiona = new THREE.DirectionalLight(0xffffff, 2.5);
        scene.add(directiona);
        //半球光
        const hemiLight = new THREE.HemisphereLight();
        scene.add(hemiLight);

        //设置背景色
        scene.background = new THREE.Color(0x031a27);

        // const GridHelper = new THREE.GridHelper(
        //     500,
        //     500,
        //     "rgb(193,193,193)",
        //     "rgb(193,193,193)"
        // );
        // scene.add(GridHelper);

        this.Scene = scene;
        this.Camera = camera;
        this.Renderer = renderer;
        this.Controls = controls;

        const _render = () => {
            if (!this.Scene) return;
            requestAnimationFrame(_render);
            TWEEN.update();
            controls.update();
            renderer.render(this.Scene, this.Camera);
        };
        _render();
    }

    //加载模型
    loadGLTF(url, callback) {
        return new Promise((resolve, reject) => {
            const loader = new GLTFLoader();
            const dracoLoader = new DRACOLoader();
            dracoLoader.setDecoderPath("/static/wasms/");
            dracoLoader.setDecoderConfig({ type: "js" });
            loader.setDRACOLoader(dracoLoader);

            loader.load(
                url,
                (gltf) => {
                    this.Scene.add(gltf.scene);

                    callback && callback(100);

                    const box = new THREE.Box3().setFromObject(gltf.scene);
                    const size = box.getSize(new THREE.Vector3()).length();
                    this.Controls.maxDistance = size * 3;
                    this.Camera.near = size / 100;
                    this.Camera.far = size * 100;

                    resolve(gltf.scene);
                },
                (xhr) => {
                    const percent = (xhr.loaded / xhr.total) * 100;
                    let progress = percent > 5 ? percent - 4 : percent;
                    callback && callback(progress);
                }
            );
        });
    }

    //销毁场景
    destroy() {
        try {
            this.Renderer.dispose();
            this.Renderer.forceContextLoss();
            this.Renderer.content = null;

            this.Renderer.domElement.addEventListener("click", null, false); //remove listener to render
            window.addEventListener("resize", null, false);
            document.addEventListener("visibilitychange", null, false);

            let gl = this.Renderer.domElement.getContext("webgl");
            if (gl && gl.getExtension("WEBGL_lose_context")) {
                gl.getExtension("WEBGL_lose_context").loseContext();
            }
            this.Renderer = null;
            this.Camera = null;
            this.Scene.traverse((child) => {
                if (child.material) {
                    if (child.material instanceof Array) {
                        child.material.forEach((item) => item.dispose());
                    } else {
                        child.material.dispose();
                        if (child.material.map) {
                            child.material.map.dispose();
                        }
                    }
                }
                if (child.geometry) {
                    child.geometry.dispose();
                    child.geometry.attributes = null;
                }
                child = null;
            });
            this.Scene = null;
            this.Controls = null;

            THREE.Cache.clear();
        } catch (e) {
            console.error("Failed to destroy threejs", e);
        }
    }
}
